#******************************************************************************
#******************************************************************************

# import libraries

# from src.hyhetra.pipes.classes import StandardisedPipe, StandardisedPipeDatabase

import src.hyhetra.pipes.fic as fic

import src.hyhetra.common.formulas as hht_core

# from src.hyhetra.common.core import ConvectionHeatTransferCoefficient

from src.hyhetra.pipes.single import PipeUnderForcedInternalCirculation

from src.hyhetra.common.factors import shape_factor_buried_horizontal_isothermal_cylinder

from src.hyhetra.common.factors import thermal_resistance_from_shape_factor

import numpy as np

from numpy.testing import assert_allclose

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

def examples(oil_db: fic.FluidDatabase, 
             water_db: fic.FluidDatabase, 
             air_db: fic.FluidDatabase):
    
    # # get oil properties' database
    
    # oildata_file = 'data/fluids/other/incropera2006_engine_oil.csv'

    # oil_db = fic.FluidDatabase(fluid='oil',
    #                            phase='l', 
    #                            source=oildata_file)
    
    # # get water properties' database
    
    # waterdata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # water_db = fic.FluidDatabase(fluid='fluid',
    #                              phase='l',
    #                              source=waterdata_file)
    
    # # get air properties' database
    
    # airdata_file = 'data/fluids/air/incropera2006_air_1atm.csv'

    # air_db = fic.FluidDatabase(fluid='air',
    #                            phase='g',
    #                            source=airdata_file)
    
    # tests
    
    cengel2003_example8dash3_fic(oil_db)
    cengel2003_example8dash3()
    cengel2003_example8dash4_pufic(water_db)
    cengel2003_example8dash4(water_db)
    
    fluid_dynamics_problem(water_db)
    cengel2003_example_8dash5_pufic(water_db)
    cengel2003_example_8dash5()
    incropera2006_example_8dot6_fic()
    incropera2006_example_8dot6(air_db)

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a fluid dynamics problem

def cengel2003_example8dash3_fic(fluiddb):
    
    # Cengel2003, Example 8-3
    
    # Consider the flow of oil at 20°C in a 30-cm-diameter pipeline at an average
    # velocity of 2 m/s (Fig. 8–23). A 200-m-long section of the pipeline passes
    # through icy waters of a lake at 0°C. Measurements indicate that the surface
    # temperature of the pipe is very nearly 0°C. Disregarding the thermal resistance
    # of the pipe material, determine (a) the temperature of the oil when the pipe
    # leaves the lake, (b) the rate of heat transfer from the oil, and (c) the pumping
    # power required to overcome the pressure losses and to maintain the flow of the
    # oil in the pipe.
    
    pipe_diameter = 0.3 # m
    
    pipe_length = 200 # m
    
    fluid_speed = 2 # m/s
    
    fluid_temperature = 20+273.15 # Celsius
    
    pipe_temperature = 0+273.15 # Celsius
    
    # fluid

    # # fluid = fic.Fluid(phase='l',
    # #                   temperature=fluid_temperature,
    # #                   pressure=1e5,
    # #                   mass_density=888, # kg/m3
    # #                   thermal_conductivity=0.145, # w/mK
    # #                   dynamic_viscosity=888*901E-6, #  3.74 lbm / ft / hour
    # #                   kinematic_viscosity=901E-6, #
    # #                   prandtl_number=10400,
    # #                   specific_heat=1880,
    # #                   coefficient_expansion=0)
    
    # fluiddata_file = 'data/fluids/other/incropera2006_engine_oil.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)
    
    fluid = fic.Fluid(phase='l',
                      temperature=fluid_temperature,
                      pressure=1e5,
                      db=fluiddb)
    
    # pipe
    
    pipe = fic.Pipe(length=pipe_length,
                    k=np.inf,
                    e_eff=0,
                    d_int=pipe_diameter,
                    d_ext=pipe_diameter)
    
    # reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed,
                                              fluid.kinematic_viscosity)
    
    # thermal entry length
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    # friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe, 
                                              flow_regime)
    
    # nusselt number
    
    nusselt_number = fic.NusseltNumber(pipe,
                                       friction_factor,
                                       reynolds_number,
                                       fluid.prandtl_number,
                                       flow_regime)
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = hht_core.ConvectionHeatTransferCoefficient(
        pipe.d_int, nusselt_number, fluid.thermal_conductivity)
    
    # thermal resistance
    
    pipe_area = pipe.length*pipe.d_int*np.pi
    
    thermal_resistance = 1/(heat_transfer_coefficient*pipe_area)

    # heat transfer condition
    
    heat_transfer_condition = fic.CONDITION_ISOTHERMAL_SURFACE
    
    # heat transfer calculations
    
    pipe_efficiency, temperature_out, _ = fic.PipeHeatTransferCalculations(
        pipe, 
        fluid, 
        fluid, 
        fluid_speed,
        heat_transfer_condition, 
        pipe_temperature, 
        thermal_resistance)
    
    # log mean temperature difference
    
    lmtd = fic.LogMeanTemperatureDifference(fluid.temperature,
                                            temperature_out,
                                            pipe_temperature)
    
    # heat flow rate
    
    heat_flow_rate = hht_core.HeatTransferRateNewtonLawCooling(
        lmtd, 
        heat_transfer_coefficient, 
        pipe.InternalSurfaceArea()) #pipe.d_int*pipe.length*np.pi
    
    # pressure drop
    
    pressure_drop = fic.SpecificPressureLossInPipe(
        fluid.mass_density,
        pipe.d_int,
        fluid_speed,
        friction_factor)*pipe.length
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMeanFluidSpeed(
        fluid_speed, pipe.InternalCrossSectionalArea())
    
    # pumping power
    
    pumping_power = fic.MechanicalPumpingPower(
        volumetric_flow_rate, 
        pressure_drop)
    
    #**************************************************************************
    
    relative_tolerance = 0.05
    
    re_true = 666
    
    re_tol = re_true*relative_tolerance
    
    nu_true = 37.3
    
    nu_tol = nu_true*relative_tolerance
    
    h_true = 18
    
    h_tol = h_true*relative_tolerance
    
    t_out_true = 19.71+273.15 # celsius
    
    t_out_tol = t_out_true*relative_tolerance
    
    ff_true = 0.0961
    
    ff_tol = ff_true*relative_tolerance
    
    lmtd_true = -19.85
    
    lmtd_tol = abs(lmtd_true)*relative_tolerance
    
    hfr_true = -6.74E4
    
    hfr_tol = abs(hfr_true)*relative_tolerance
    
    pd_true = 1.14E5
    
    pd_tol = pd_true*relative_tolerance
    
    pp_true = 16.1E3
    
    pp_tol = pp_true*relative_tolerance

    #**************************************************************************
    
    assert reynolds_number <= re_true + re_tol
    
    assert reynolds_number >= re_true - re_tol
    
    assert nusselt_number <= nu_true + nu_tol
    
    assert nusselt_number >= nu_true - nu_tol
    
    assert friction_factor <= ff_true + ff_tol
    
    assert friction_factor >= ff_true - ff_tol
    
    assert heat_transfer_coefficient <= h_true + h_tol
    
    assert heat_transfer_coefficient >= h_true - h_tol
    
    assert temperature_out <= t_out_true + t_out_tol
    
    assert temperature_out >= t_out_true - t_out_tol
    
    assert lmtd <= lmtd_true + lmtd_tol
    
    assert lmtd >= lmtd_true - lmtd_tol
    
    assert pressure_drop <= pd_true + pd_tol
    
    assert pressure_drop >= pd_true - pd_tol
    
    assert pumping_power <= pp_true + pp_tol
    
    assert pumping_power >= pp_true - pp_tol
    
    assert heat_flow_rate <= hfr_true + hfr_tol
    
    assert heat_flow_rate >= hfr_true - hfr_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a fluid dynamics problem

def cengel2003_example8dash3():
    
    # Cengel2003, Example 8-3
    
    # Consider the flow of oil at 20°C in a 30-cm-diameter pipeline at an average
    # velocity of 2 m/s (Fig. 8–23). A 200-m-long section of the pipeline passes
    # through icy waters of a lake at 0°C. Measurements indicate that the surface
    # temperature of the pipe is very nearly 0°C. Disregarding the thermal resistance
    # of the pipe material, determine (a) the temperature of the oil when the pipe
    # leaves the lake, (b) the rate of heat transfer from the oil, and (c) the pumping
    # power required to overcome the pressure losses and to maintain the flow of the
    # oil in the pipe.
    
    pipe_diameter = 0.3 # m
    
    pipe_length = 200 # m
    
    fluid_speed = 2 # m/s
    
    fluid_temperature = 20+273.15 # Celsius
    
    pipe_temperature = 0+273.15 # Celsius
    
    # fluid

    fluid = fic.Fluid(phase='l',
                      temperature=fluid_temperature,
                      pressure=1e5,
                      mass_density=888, # kg/m3
                      thermal_conductivity=0.145, # w/mK
                      dynamic_viscosity=888*901E-6, #  3.74 lbm / ft / hour
                      kinematic_viscosity=901E-6, #
                      prandtl_number=10400,
                      specific_heat=1880,
                      coefficient_expansion=0)
    
    # pipe
    
    pipe = fic.Pipe(length=pipe_length,
                    k=np.inf,
                    e_eff=0,
                    d_int=pipe_diameter,
                    d_ext=pipe_diameter)
    
    # reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed,
                                              fluid.kinematic_viscosity)
    
    # thermal entry length
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    # friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe, 
                                              flow_regime)
    
    # nusselt number
    
    nusselt_number = fic.NusseltNumber(pipe,
                                       friction_factor,
                                       reynolds_number,
                                       fluid.prandtl_number,
                                       flow_regime)
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = hht_core.ConvectionHeatTransferCoefficient(
        pipe.d_int, nusselt_number, fluid.thermal_conductivity)
    
    # thermal resistance
    
    pipe_area = pipe.length*pipe.d_int*np.pi
    
    thermal_resistance = 1/(heat_transfer_coefficient*pipe_area)

    # heat transfer condition
    
    heat_transfer_condition = fic.CONDITION_ISOTHERMAL_SURFACE
    
    # heat transfer calculations
    
    pipe_efficiency, temperature_out, _ = fic.PipeHeatTransferCalculations(
        pipe, 
        fluid, 
        fluid, 
        fluid_speed,
        heat_transfer_condition, 
        pipe_temperature, 
        thermal_resistance)
    
    # log mean temperature difference
    
    lmtd = fic.LogMeanTemperatureDifference(fluid.temperature,
                                            temperature_out,
                                            pipe_temperature)
    
    # heat flow rate
    
    heat_flow_rate = hht_core.HeatTransferRateNewtonLawCooling(
        lmtd, 
        heat_transfer_coefficient, 
        pipe.InternalSurfaceArea())
    
    # pressure drop
    
    pressure_drop = fic.SpecificPressureLossInPipe(
        fluid.mass_density,
        pipe.d_int,
        fluid_speed,
        friction_factor)*pipe.length
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMeanFluidSpeed(
        fluid_speed, pipe.InternalCrossSectionalArea())
    
    # pumping power
    
    pumping_power = fic.MechanicalPumpingPower(
        volumetric_flow_rate, 
        pressure_drop)
    
    #**************************************************************************
    
    relative_tolerance = 0.05
    
    re_true = 666
    
    re_tol = re_true*relative_tolerance
    
    nu_true = 37.3
    
    nu_tol = nu_true*relative_tolerance
    
    h_true = 18
    
    h_tol = h_true*relative_tolerance
    
    t_out_true = 19.71+273.15 # celsius
    
    t_out_tol = t_out_true*relative_tolerance
    
    ff_true = 0.0961
    
    ff_tol = ff_true*relative_tolerance
    
    lmtd_true = -19.85
    
    lmtd_tol = abs(lmtd_true)*relative_tolerance
    
    hfr_true = -6.74E4
    
    hfr_tol = abs(hfr_true)*relative_tolerance
    
    pd_true = 1.14E5
    
    pd_tol = pd_true*relative_tolerance
    
    pp_true = 16.1E3
    
    pp_tol = pp_true*relative_tolerance

    #**************************************************************************
    
    assert reynolds_number <= re_true + re_tol
    
    assert reynolds_number >= re_true - re_tol
    
    assert nusselt_number <= nu_true + nu_tol
    
    assert nusselt_number >= nu_true - nu_tol
    
    assert friction_factor <= ff_true + ff_tol
    
    assert friction_factor >= ff_true - ff_tol
    
    assert heat_transfer_coefficient <= h_true + h_tol
    
    assert heat_transfer_coefficient >= h_true - h_tol
    
    assert temperature_out <= t_out_true + t_out_tol
    
    assert temperature_out >= t_out_true - t_out_tol
    
    assert lmtd <= lmtd_true + lmtd_tol
    
    assert lmtd >= lmtd_true - lmtd_tol
    
    assert pressure_drop <= pd_true + pd_tol
    
    assert pressure_drop >= pd_true - pd_tol
    
    assert pumping_power <= pp_true + pp_tol
    
    assert pumping_power >= pp_true - pp_tol
    
    assert heat_flow_rate <= hfr_true + hfr_tol
    
    assert heat_flow_rate >= hfr_true - hfr_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a fluid dynamics problem

def cengel2003_example8dash4_pufic(fluiddb):
    
    # Cengel2003, example 8-4, page 445
    
    # Water at 60°F (density = 62.36 lbm/ft 3 and viscosity = 2.713 lbm/ft x h) 
    # is flowing steadily in a 2-in.-diameter horizontal pipe made of stainless 
    # steel at a rate of 0.2 ft^3 /s (Fig. 8–28). Determine the pressure drop 
    # and the  required pumping power input for flow through a 200-ft-long
    # section of the pipe.
    
    #**************************************************************************

    # specify fluid database
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'
    
    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)
    
    # pipe length
    
    pipe_length = 60.96 # 200 ft = 60.96 m
    
    # pipe diameter
    
    pipe_diameter = 0.0508 # 2 inch = 0.0508 m
    
    # pipe external diameter
    
    pipe_external_diameter = pipe_diameter + 0.005
    
    # pipe absolute roughness
    
    pipe_absolute_roughness = 2.1336E-06
    
    # volumetric flow rate
    
    volumetric_flow_rate = 0.0056633693 # 0.2 ft^3/s = 0.0056633693 m^3/s
    
    # inlet temperature
    
    temperature_inlet = 15.555556 # 60º F = 15.555556º Celsius
    
    # define pipe object
    
    # pipe = fic.Pipe(length=pipe_length,
    #                 k=160,
    #                 e_eff=pipe_absolute_roughness,
    #                 d_int=pipe_diameter,
    #                 d_ext=pipe_external_diameter)
    
    pipe = fic.InsulatedPipe(length=pipe_length,
                             k=160,
                             e_eff=pipe_absolute_roughness,
                             d_int=pipe_diameter,
                             d_ext=pipe_external_diameter,
                             d_ins=pipe_external_diameter,
                             k_ins=160,
                             d_cas=pipe_external_diameter,
                             k_cas=160)
        
    # fluid speed
    
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, 
        pipe.InternalCrossSectionalArea())

    # define fluid object
    
    fluid = fic.Fluid(phase='l',
                      temperature=273.15+temperature_inlet,
                      pressure=0,
                      db=fluiddb)
    
    # create pufic object
    
    pufic = PipeUnderForcedInternalCirculation(
        pipe,
        fluid, 
        fluiddb,
        pipe_heat_flux=0,
        volumetric_flow_rate=volumetric_flow_rate)
    
    #**************************************************************************
    
    # fluid speed
    
    # mass flow rate

    # calculate the reynolds number
    
    reynolds_number = pufic.reynolds_number
    
    # flow regime
    
    flow_regime = pufic.flow_regime
    
    # calculate the friction factor
    
    friction_factor = pufic.friction_factor
                                              
    # calculate the pressure drop
        
    specific_pressure_drop = pufic.specific_pressure_drop
    
    pressure_drop = specific_pressure_drop*pipe.length
    
    # pumping power
    
    pumping_power = pressure_drop*volumetric_flow_rate
    
    relative_tolerance = 0.025
    
    #**************************************************************************
    
    re_true = 126400
    
    ff_true = 0.0174
    
    pd_true = 81358.136
    
    pp_true = 461
    
    #**************************************************************************
    
    # reynolds number
    
    re_tol = re_true*relative_tolerance
    
    assert reynolds_number <= re_true+re_tol
    
    assert reynolds_number >= re_true-re_tol
    
    #**************************************************************************
    
    # friction factor
    
    ff_tol = ff_true*relative_tolerance
    
    assert friction_factor <= ff_true+ff_tol
    
    assert friction_factor >= ff_true-ff_tol
    
    #**************************************************************************
    
    # pressure drop
    
    pd_tol = pd_true*relative_tolerance
    
    assert pressure_drop <= pd_true+pd_tol
    
    assert pressure_drop >= pd_true-pd_tol
    
    #**************************************************************************
    
    # pumping power
    
    pp_tol = pp_true*relative_tolerance
    
    assert pumping_power <= pp_true+pp_tol
    
    assert pumping_power >= pp_true-pp_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a fluid dynamics problem

def cengel2003_example8dash4(fluiddb):
    
    # Cengel2003, example 8-4, page 445
    
    # Water at 60°F (density = 62.36 lbm/ft 3 and viscosity = 2.713 lbm/ft x h) 
    # is flowing steadily in a 2-in.-diameter horizontal pipe made of stainless 
    # steel at a rate of 0.2 ft^3 /s (Fig. 8–28). Determine the pressure drop 
    # and the  required pumping power input for flow through a 200-ft-long
    # section of the pipe.
    
    #**************************************************************************
    
    # pipe length
    
    pipe_length = 60.96 # 200 ft = 60.96 m
    
    # pipe diameter
    
    pipe_diameter = 0.0508 # 2 inch = 0.0508 m
    
    # pipe external diameter
    
    pipe_external_diameter = pipe_diameter + 0.005
    
    # pipe absolute roughness
    
    pipe_absolute_roughness = 2.1336E-06
    
    # volumetric flow rate
    
    volumetric_flow_rate = 0.0056633693 # 0.2 ft^3/s = 0.0056633693 m^3/s
    
    # inlet temperature
    
    temperature_inlet = 15.555556 # 60º F = 15.555556º Celsius
    
    # define pipe object
    
    pipe = fic.Pipe(length=pipe_length,
                    k=160,
                    e_eff=pipe_absolute_roughness,
                    d_int=pipe_diameter,
                    d_ext=pipe_external_diameter)
                    
    # fluid speed
    
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, 
        pipe.InternalCrossSectionalArea())
    
    # specify fluid database
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)

    # define fluid object
    
    fluid = fic.Fluid(phase='l',
                      temperature=273.15+temperature_inlet,
                      pressure=0,
                      db=fluiddb)
    
    # fluid = fic.Fluid(phase='l',
    #                   temperature=273.15+temperature_inlet,
    #                   pressure=1e5,
    #                   mass_density=999.87248, # 62.42 lbm/ft3
    #                   thermal_conductivity=0.631,
    #                   dynamic_viscosity=0.001546037, #  3.74 lbm / ft / hour
    #                   kinematic_viscosity=0.658E-6,
    #                   prandtl_number=4.32,
    #                   surface_tension=0,
    #                   heat_vaporisation=0,
    #                   specific_heat=4179,
    #                   coefficient_expansion=0)
    
    #**************************************************************************

    # calculate the reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed, 
                                              fluid.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    # calculate the friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
                                              
    # calculate the pressure drop
        
    specific_pressure_drop = fic.SpecificPressureLossInPipe(
        fluid.mass_density,
        pipe.d_int,
        fluid_speed,
        friction_factor)
    
    pressure_drop = specific_pressure_drop*pipe.length
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMeanFluidSpeed(
        fluid_speed, 
        pipe.InternalCrossSectionalArea())
    
    # pumping power
    
    pumping_power = pressure_drop*volumetric_flow_rate
    
    relative_tolerance = 0.025
    
    #**************************************************************************
    
    re_true = 126400
    
    ff_true = 0.0174
    
    pd_true = 81358.136
    
    pp_true = 461
    
    #**************************************************************************
    
    # reynolds number
    
    re_tol = re_true*relative_tolerance
    
    assert reynolds_number <= re_true+re_tol
    
    assert reynolds_number >= re_true-re_tol
    
    #**************************************************************************
    
    # friction factor
    
    ff_tol = ff_true*relative_tolerance
    
    assert friction_factor <= ff_true+ff_tol
    
    assert friction_factor >= ff_true-ff_tol
    
    #**************************************************************************
    
    # pressure drop
    
    pd_tol = pd_true*relative_tolerance
    
    assert pressure_drop <= pd_true+pd_tol
    
    assert pressure_drop >= pd_true-pd_tol
    
    #**************************************************************************
    
    # pumping power
    
    pp_tol = pp_true*relative_tolerance
    
    assert pumping_power <= pp_true+pp_tol
    
    assert pumping_power >= pp_true-pp_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a fluid dynamics problem

def fluid_dynamics_problem(fluiddb):
    
    # Water at 40°F (  62.42 lbm/ft 3 and   3.74 lbm/ft  h) is flowing in
    # a 0.15 in. diameter 30-ft-long pipe steadily at an average velocity of 
    # 3 ft/s (Fig. 8–22).
    # Determine the pressure drop and the pumping power requirement to overcome
    # this pressure drop.
    
    #**************************************************************************
    
    # fluid speed
    
    fluid_speed = 0.9144 # 3 ft/s = 0.9144 m/s
    
    # inlet temperature
    
    temperature_inlet = 4.4444444 # 40º F = 4.4444444º Celsius
    
    # pipe length
    
    pipe_length = 9.144 # 30 ft = 9.144 m
    
    # pipe diameter
    
    pipe_diameter = 0.00381 # 0.15 inch = 0.00381 m
    
    # specify fluid database
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
        
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)

    # define fluid object
    
    fluid = fic.Fluid(phase='l',
                      temperature=273.15+temperature_inlet,
                      pressure=0,
                      db=fluiddb)
    
    # fluid = fic.Fluid(phase='l',
    #                   temperature=273.15+temperature_inlet,
    #                   pressure=1e5,
    #                   mass_density=999.87248, # 62.42 lbm/ft3
    #                   thermal_conductivity=0.631,
    #                   dynamic_viscosity=0.001546037, #  3.74 lbm / ft / hour
    #                   kinematic_viscosity=0.658E-6,
    #                   prandtl_number=4.32,
    #                   specific_heat=4179,
    #                   coefficient_expansion=0)
    
    # define pipe object
    
    pipe = fic.Pipe(length=pipe_length,
                    k=400,
                    e_eff=1e-3,
                    d_int=pipe_diameter,
                    d_ext=pipe_diameter+1e-3)
    
    #**************************************************************************

    # calculate the reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed, 
                                              fluid.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    # calculate the friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
                                              
    # calculate the pressure drop
        
    specific_pressure_drop = fic.SpecificPressureLossInPipe(
        fluid.mass_density,
        pipe.d_int,
        fluid_speed,
        friction_factor)
    
    pressure_drop = specific_pressure_drop*pipe.length
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMeanFluidSpeed(
        fluid_speed, 
        pipe.InternalCrossSectionalArea())
    
    # pumping power
    
    pumping_power = pressure_drop*volumetric_flow_rate
    
    #**************************************************************************
    
    # reynolds number
    
    re_true = 2254 # 1803 in the book
    
    re_tol = re_true*0.05
    
    assert reynolds_number <= re_true+re_tol
    
    assert reynolds_number >= re_true-re_tol
    
    #**************************************************************************
    
    # friction factor
    
    ff_true = 0.0355
    
    ff_tol = 0.02
    
    assert friction_factor <= ff_true+ff_tol
    
    assert friction_factor >= ff_true-ff_tol
    
    #**************************************************************************
    
    # pressure drop
    
    pd_true = 44540.132 # 6.46 psi = 44540.132 Pa
    
    pd_tol = pd_true*0.4
    
    assert pressure_drop <= pd_true+pd_tol
    
    assert pressure_drop >= pd_true-pd_tol
    
    #**************************************************************************
    
    # pumping power
    
    pp_true = 0.3
    
    pp_tol = 0.05
    
    assert pumping_power <= pp_true+pp_tol
    
    assert pumping_power >= pp_true-pp_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a heat transfer problem

def cengel2003_example_8dash5_pufic(fluiddb):
    
    # Cengel2003, page 446, Example 8-5
        
    #**************************************************************************
    
    phf_true = 73.46e3 # kW/m2
    
    mfr_true = 0.1654 # Kg/s
    
    mfs_true = 0.236 #m/s
    
    hfr_true = 34.6e3
    
    re_true = 10760
    
    nu_true = 69.5
    
    htc_true = 1462 # W/m2C
    
    pst_true = 115+273.15 # pipe surface temperature near outlet
    
    # relative tolerance
    
    relative_tolerance = 0.025
    
    #**************************************************************************
    
    # specify fluid database
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)
    
    #**************************************************************************
    
    # inlet temperature
    
    temperature_inlet = 273.15+15 # Celsius
    
    # outlet temperature
    
    temperature_outlet = 273.15+65 # Celsius
    
    # bulk temperature
    
    fluid_temperature_bulk = (temperature_inlet+
                              temperature_outlet)/2
    
    # volumetric flow rate
    
    volumetric_flow_rate = (10/60)/1E3 # 10 L/min = 10/60 L/s = 1e-3*10/60 m3/s
    
    # define pipe object
    
    pipe = fic.InsulatedPipe(length=5,
                             k=400,
                             e_eff=0.01/1000,
                             d_int=0.03,
                             d_ext=0.03,
                             d_ins=0.03,
                             k_ins=0.05,
                             d_cas=0.03,
                             k_cas=0.50)
    
    # define fluid object
    
    fluid = fic.Fluid(phase='l',
                      temperature=temperature_inlet,
                      pressure=1e5,
                      db=fluiddb)
    
    # create pufic object
    
    pufic = PipeUnderForcedInternalCirculation(
        pipe,
        fluid, 
        fluiddb,
        pipe_heat_flux=phf_true,
        volumetric_flow_rate=volumetric_flow_rate,
        bulk_temperature=fluid_temperature_bulk)
                      
    # fluid mean speed
    
    fluid_speed = pufic.fluid_speed
    
    # mass flow rate
    
    mass_flow_rate = pufic.mass_flow_rate
    
    # calculate the reynolds number
    
    reynolds_number = pufic.reynolds_number
    
    # nusselt number
    
    nusselt_number = pufic.nusselt_number
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = pufic.heat_transfer_coefficient
    
    # calculate the heat flow rate
    
    # heat_flow_rate = pufic.heat_transfer_rate
    
    heat_flow_rate = fic.HeatTransferRateInPipe(fluid_speed, 
                                                fluid, 
                                                pufic.fluid_outlet, 
                                                pipe,
                                                fluid_bulk=pufic.fluid_bulk)
    
    # pipe surface temperature at the exit
    
    pipe_surface_temperature = (
        temperature_outlet+
        (heat_flow_rate/(np.pi*pipe.d_int*pipe.length))/
        heat_transfer_coefficient
        )
    
    #**************************************************************************
    
    # mass flow rate
    
    mfr_tol = mfr_true*relative_tolerance
    
    assert mass_flow_rate <= mfr_true+mfr_tol
    
    assert mass_flow_rate >= mfr_true-mfr_tol
    
    # fluid speed
    
    mfs_tol = mfs_true*relative_tolerance
    
    assert fluid_speed <= mfs_true+mfs_tol
    
    assert fluid_speed >= mfs_true-mfs_tol
    
    # bulk temperature
    
    bt_tol = pufic.bulk_temperature_tolerance
    
    assert pufic.bulk_temperature <= fluid_temperature_bulk+bt_tol
    
    assert pufic.bulk_temperature >= fluid_temperature_bulk-bt_tol
    
    # reynolds number
    
    re_tol = re_true*relative_tolerance
    
    assert reynolds_number <= re_true+re_tol
    
    assert reynolds_number >= re_true-re_tol
    
    # nusselt number
    
    nu_tol = nu_true*relative_tolerance
    
    assert nusselt_number <= nu_true+nu_tol
    
    assert nusselt_number >= nu_true-nu_tol
    
    # heat transfer coefficient
    
    htc_tol = htc_true*relative_tolerance
    
    assert heat_transfer_coefficient <= htc_true+htc_tol
    
    assert heat_transfer_coefficient >= htc_true-htc_tol
    
    # outlet temperature
    
    tout_tol = temperature_outlet*relative_tolerance
    
    assert pufic.outlet_temperature <= temperature_outlet+tout_tol
    
    assert pufic.outlet_temperature >= temperature_outlet-tout_tol
    
    # pipe surface temperature at the exit/outlet
    
    pst_tol = pst_true*relative_tolerance
    
    assert pipe_surface_temperature <= pst_true+pst_tol
    
    assert pipe_surface_temperature >= pst_true-pst_tol
    
    # heat flow rate
    
    hfr_tol = hfr_true*relative_tolerance
    
    assert heat_flow_rate <= hfr_true+hfr_tol
    
    assert heat_flow_rate >= hfr_true-hfr_tol
    
    #**************************************************************************
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a heat transfer problem

def cengel2003_example_8dash5():
    
    # Cengel2003, page 446, Example 8-5
    
    # inlet temperature
    
    temperature_inlet = 15 # Celsius
    
    # outlet temperature
    
    temperature_outlet = 65 # Celsius
    
    # volumetric flow rate
    
    volumetric_flow_rate = (10/60)/1E3 # 10 L/min = 10/60 L/s = 1e-3*10/60 m3/s
    
    # define pipe object
    
    pipe = fic.Pipe(length=5,
                    k=400,
                    e_eff=1e-3,
                    d_int=0.03,
                    d_ext=0.04)
    
    # define fluid object
    
    bulk_mean_temperature = (temperature_outlet+temperature_inlet)/2
    
    fluid = fic.Fluid(phase='l',
                      temperature=273.15+bulk_mean_temperature,
                      pressure=1e5,
                      mass_density=992.1,
                      thermal_conductivity=0.631,
                      dynamic_viscosity=992.1*0.658E-6,
                      kinematic_viscosity=0.658E-6,
                      prandtl_number=4.32,
                      specific_heat=4179,
                      coefficient_expansion=0)
                      
    # fluid mean speed
    
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, 
        pipe.InternalCrossSectionalArea())
    
    # mass flow rate
    
    mass_flow_rate = hht_core.MassFlowRateFromVolumetricFlowRate(
        volumetric_flow_rate, 
        fluid.mass_density)
    
    # calculate the heat flow rate
    
    heat_flow_rate = mass_flow_rate*fluid.specific_heat*(
        temperature_outlet-temperature_inlet)
    
    # calculate the reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed, 
                                              fluid.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
                                              
    # calculate the friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
    
    # nusselt number
    
    # nusselt_number = fic.NusseltNumber(pipe, 
    #                                    friction_factor, 
    #                                    reynolds_number, 
    #                                    fluid.prandtl_number)
    
    nusselt_number = fic.NusseltNumber_ColburnDittusBoelter(
        reynolds_number, 
        fluid.prandtl_number,
        mode='heating')
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = (
        nusselt_number*fluid.thermal_conductivity/pipe.d_int)
    
    # pipe surface temperature at the exit
    
    pipe_surface_temperature = (
        temperature_outlet+
        (heat_flow_rate/(np.pi*pipe.d_int*pipe.length))/
        heat_transfer_coefficient)
        
    #**************************************************************************
    
    mfr_true = 0.1654 # Kg/s
    
    hfr_true = 34.6e3
    
    re_true = 10760
    
    nu_true = 69.5
    
    htc_true = 1462 # W/m2C
    
    pst_true = 115
    
    # relative tolerance
    
    relative_tolerance = 0.05
    
    #**************************************************************************
    
    # mass flow rate
    
    mfr_tol = mfr_true*relative_tolerance
    
    assert mass_flow_rate <= mfr_true+mfr_tol
    
    assert mass_flow_rate >= mfr_true-mfr_tol
    
    # heat flow rate
    
    hfr_tol = hfr_true*relative_tolerance
    
    assert heat_flow_rate <= hfr_true+hfr_tol
    
    assert heat_flow_rate >= hfr_true-hfr_tol
    
    # reynolds number
    
    re_tol = re_true*relative_tolerance
    
    assert reynolds_number <= re_true+re_tol
    
    assert reynolds_number >= re_true-re_tol
    
    # nusselt number
    
    nu_tol = nu_true*relative_tolerance
    
    assert nusselt_number <= nu_true+nu_tol
    
    assert nusselt_number >= nu_true-nu_tol
    
    # heat transfer coefficient
    
    htc_tol = htc_true*relative_tolerance
    
    assert heat_transfer_coefficient <= htc_true+htc_tol
    
    assert heat_transfer_coefficient >= htc_true-htc_tol
    
    # pipe surface temperature at the exit/outlet
    
    pst_tol = pst_true*relative_tolerance
    
    assert pipe_surface_temperature <= pst_true+pst_tol
    
    assert pipe_surface_temperature >= pst_true-pst_tol
    
    #**************************************************************************
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a heat transfer problem

def incropera2006_example_8dot6_fic():
    
    # Incropera2006, page 516, Example 8.6
    
    # inlet temperature
    
    temperature_inlet = 103+273.15 # kelvin
    
    # outlet temperature
    
    temperature_outlet = 77+273.15 # kelvin
    
    # temperature surroundings 
    
    temperature_surroundings = 0+273.15 # kelvins
    
    # heat transfer coefficient for external convection
    
    h_conv_outside = 6
    
    # define pipe object
    
    pipe = fic.Pipe(length=5,
                    k=400,
                    e_eff=1e-3,
                    d_int=0.15,
                    d_ext=0.15)
    
    # define fluid object
    
    bulk_mean_temperature = (temperature_outlet+temperature_inlet)/2
    
    fluid = fic.Fluid(phase='g',
                      temperature=bulk_mean_temperature,
                      pressure=1e5,
                      mass_density=0.9950,
                      thermal_conductivity=0.03,
                      dynamic_viscosity=208.2E-7,
                      kinematic_viscosity=20.92E-6,
                      prandtl_number=0.7,
                      specific_heat=1009,
                      coefficient_expansion=0)
              
    # mass flow rate
    
    mass_flow_rate = 0.05 # Kg/s
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMassFlowRate(
        mass_flow_rate, fluid.mass_density)
                      
    # fluid mean speed
        
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, pipe.InternalCrossSectionalArea())
    
    # calculate the heat flow rate
    
    heat_flow_rate = mass_flow_rate*fluid.specific_heat*(
        temperature_outlet-temperature_inlet)
    
    # calculate the reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed, 
                                              fluid.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
                                              
    # calculate the friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
    
    # nusselt number
    
    # nusselt_number = fic.NusseltNumber(pipe, 
    #                                    friction_factor, 
    #                                    reynolds_number, 
    #                                    fluid.prandtl_number)
    
    nusselt_number = fic.NusseltNumber_ColburnDittusBoelter(
        reynolds_number, 
        fluid.prandtl_number,
        mode='heating')
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = (
        nusselt_number*fluid.thermal_conductivity/pipe.d_int)
    
    # heat flux
    
    heat_flux = (
        -(temperature_outlet-temperature_surroundings)/
        (1/heat_transfer_coefficient+1/h_conv_outside)
        )
    
    # pipe surface temperature at the exit
    
    pipe_surface_temperature = (
        temperature_outlet+
        (heat_flux)/
        heat_transfer_coefficient)
    
    #**************************************************************************

    relative_tolerance = 0.05
    
    hfr_true = -1313
    
    re_true = 20384
    
    nu_true = 57.9
    
    htc_true = 11.6 # W/m2C
    
    hf_true = -304.5 # W/m2
    
    pst_true = 50.7+273.15
    
    #**************************************************************************
    
    # heat flow rate
    
    assert_allclose(heat_flow_rate, hfr_true, relative_tolerance)
    
    #**************************************************************************
    
    # reynolds number
    
    assert_allclose(reynolds_number, re_true, relative_tolerance)
    
    #**************************************************************************
    
    # nusselt number
    
    assert_allclose(nusselt_number, nu_true, relative_tolerance)
    
    #**************************************************************************
    
    # heat transfer coefficient
    
    assert_allclose(heat_transfer_coefficient, htc_true, relative_tolerance)

    #**************************************************************************
    
    # heat flux
    
    assert_allclose(heat_flux, hf_true, relative_tolerance)
    
    #**************************************************************************
    
    # pipe surface temperature at the exit/outlet
    
    assert_allclose(pipe_surface_temperature, pst_true, relative_tolerance)
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# test the package using a heat transfer problem

def incropera2006_example_8dot6(fluiddb):
    
    # Incropera2006, page 516, Example 8.6
    
    # inlet temperature
    
    temperature_inlet = 103+273.15 # kelvin
    
    # outlet temperature
    
    temperature_outlet = 77+273.15 # kelvin
    
    # temperature surroundings 
    
    temperature_surroundings = 0+273.15 # kelvins
    
    # heat transfer coefficient for external convection
    
    h_conv_outside = 6
    
    # define pipe object
    
    pipe = fic.Pipe(length=5,
                    k=400,
                    e_eff=0*1e-3,
                    d_int=0.15,
                    d_ext=0.15)
    
    # define fluid object
    
    # fluiddata_file = 'data/fluids/air/incropera2006_air_1atm.csv'

    # fluiddb = fic.FluidDatabase(fluid='air', phase='g', source=fluiddata_file)
    
    bulk_mean_temperature = (temperature_outlet+temperature_inlet)/2
    
    # fluid = fic.Fluid(phase='g',
    #                   temperature=bulk_mean_temperature,
    #                   pressure=1e5,
    #                   mass_density=0.9950,
    #                   thermal_conductivity=0.03,
    #                   dynamic_viscosity=208.2E-7,
    #                   kinematic_viscosity=20.92E-6,
    #                   prandtl_number=0.7,
    #                   specific_heat=1009,
    #                   coefficient_expansion=0)
                          
    fluid = fic.Fluid(phase='g',
                      temperature=bulk_mean_temperature,
                      pressure=1e5,
                      db=fluiddb)
              
    # mass flow rate
    
    mass_flow_rate = 0.05 # Kg/s
    
    # volumetric flow rate
    
    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMassFlowRate(
        mass_flow_rate, fluid.mass_density)
                      
    # fluid mean speed
        
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, pipe.InternalCrossSectionalArea())
    
    # calculate the heat flow rate
    
    heat_flow_rate = mass_flow_rate*fluid.specific_heat*(
        temperature_outlet-temperature_inlet)
    
    # calculate the reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed, 
                                              fluid.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
                                              
    # calculate the friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
    
    # nusselt number
    
    # nusselt_number = fic.NusseltNumber(pipe, 
    #                                    friction_factor, 
    #                                    reynolds_number,
    #                                    fluid.prandtl_number,
    #                                    flow_regime)
    
    # fluid.prandtl_number = 0.7
    
    nusselt_number = fic.NusseltNumber_ColburnDittusBoelter(
        reynolds_number, 
        0.7,
        mode='cooling')
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = (
        nusselt_number*fluid.thermal_conductivity/pipe.d_int)
    
    # heat flux
    
    heat_flux = (
        -(temperature_outlet-temperature_surroundings)/
        (1/heat_transfer_coefficient+1/h_conv_outside)
        )
    
    # pipe surface temperature at the exit
    
    pipe_surface_temperature = (
        temperature_outlet+
        (heat_flux)/
        heat_transfer_coefficient)
    
    #**************************************************************************

    relative_tolerance = 0.05
    
    hfr_true = -1313
    
    re_true = 20384
    
    nu_true = 57.9
    
    htc_true = 11.6 # W/m2C
    
    hf_true = -304.5 # W/m2
    
    pst_true = 50.7+273.15
    
    #**************************************************************************
    
    # heat flow rate
    
    assert_allclose(heat_flow_rate, hfr_true, relative_tolerance)
    
    #**************************************************************************
    
    # reynolds number
    
    assert_allclose(reynolds_number, re_true, relative_tolerance)
    
    #**************************************************************************
    
    # nusselt number
    
    assert_allclose(nusselt_number, nu_true, relative_tolerance)
    
    #**************************************************************************
    
    # heat transfer coefficient
    
    assert_allclose(heat_transfer_coefficient, htc_true, relative_tolerance)

    #**************************************************************************
    
    # heat flux
    
    assert_allclose(heat_flux, hf_true, relative_tolerance)
    
    #**************************************************************************
    
    # pipe surface temperature at the exit/outlet
    
    assert_allclose(pipe_surface_temperature, pst_true, relative_tolerance)
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

def test_incropera2006_example8dot4():
    
    # specify pipe database
    # Incropera2006: Example 8.4, page 507
                    
    pipe = fic.InsulatedPipe(length=6.65,
                             k=400,
                             e_eff=0,
                             d_int=0.06,
                             d_ext=0.06,
                             d_ins=0.06,
                             k_ins=0.06,
                             d_cas=0.06,
                             k_cas=0.06)
    
    # heat flux
    
    pipe_heat_flux = 2000 # W/m^2

    # mass flow rate
    
    mass_flow_rate = 0.01
    
    # specify fluid temperature
    
    fluid_temperature_inlet = 273.15+20 # kelvins
    
    fluid_temperature_outlet = 273.15+80 # kelvins
    
    #**************************************************************************
    
    # specify fluid database
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
    
    fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)
    
    fluid_temperature_bulk = (fluid_temperature_inlet+
                              fluid_temperature_outlet)/2
                              
    #**************************************************************************
    
    # specify fluid
    
    fluid_in = fic.Fluid(phase='l',
                         temperature=fluid_temperature_inlet,
                         pressure=0,
                         db=fluiddb)
                         
    fluid_out = fic.Fluid(phase='l',
                          temperature=fluid_temperature_outlet,
                          pressure=0,
                          db=fluiddb)
                         
    fluid_bulk = fic.Fluid(phase='l',
                           temperature=fluid_temperature_bulk,
                           pressure=0,
                           db=fluiddb)
    
    # flow conditions
    
    (fluid_speed,
     _,
     volumetric_flow_rate) = fic.calculateFlowRegimeTuple(
         pipe, 
         fluid_bulk, 
         mass_flow_rate=mass_flow_rate)
    
    # reynolds number
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed,
                                              fluid_out.kinematic_viscosity)
    
    # flow regime
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    # friction factor
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe, 
                                              flow_regime)
    
    # nusselt number
    
    nusselt_number = fic.NusseltNumber(pipe, 
                                       friction_factor, 
                                       reynolds_number, 
                                       fluid_out.prandtl_number, 
                                       flow_regime)
    
    # heat transfer coefficient
    
    heat_transfer_coefficient = hht_core.ConvectionHeatTransferCoefficient(
        pipe.d_int,
        nusselt_number,
        fluid_out.thermal_conductivity)

    #**************************************************************************
    
    pr_true = 2.2
    
    u_true = 356e-6 # Ns/m2
    
    k_true = 0.67 # 
    
    re_true = 603 # 
    
    h_true = 48.7
    
    nu_true = 4.36
    
    relative_tolerance = 0.05
    
    #**************************************************************************
    
    # prandtl number
    
    pr_tol = pr_true*relative_tolerance
    
    assert fluid_out.prandtl_number <= pr_true + pr_tol
    
    assert fluid_out.prandtl_number >= pr_true - pr_tol
    
    # thermal conductivity 
    
    k_tol = k_true*relative_tolerance
    
    assert fluid_out.thermal_conductivity <= k_true + k_tol
    
    assert fluid_out.thermal_conductivity >= k_true - k_tol
    
    # dynamic viscosity
    
    u_tol = u_true*relative_tolerance
    
    assert fluid_out.dynamic_viscosity <= u_true + u_tol
    
    assert fluid_out.dynamic_viscosity >= u_true - u_tol
    
    # reynolds number
    
    re_tol = re_true*relative_tolerance
    
    assert reynolds_number <= re_true + re_tol
    
    assert reynolds_number >= re_true - re_tol
    
    # nusselt_number 
    
    nu_tol = nu_true*relative_tolerance
    
    assert nusselt_number <= nu_true + nu_tol
    
    assert nusselt_number >= nu_true - nu_tol
    
    # heat transfer coefficient 
    
    h_tol = h_true*relative_tolerance
    
    assert heat_transfer_coefficient <= h_true + h_tol
    
    assert heat_transfer_coefficient >= h_true - h_tol

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

def test_duffie2013_3_14_1():
    
    # example 3.14.1 from Duffie2013
    
    # the fluid is water
    
    # fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    # fluiddb = fic.FluidDatabase(fluid='fluid', source=fluiddata_file)
    
    fluiddata_file = 'data/fluids/water/incropera2006_saturated_water.csv'

    fluiddb = fic.FluidDatabase(fluid='fluid', phase='l', source=fluiddata_file)
    
    # fluid temperature
    
    fluid_inlet_temperature = 273.15+80
    
    # define fluid object
    
    fluid = fic.Fluid(temperature=fluid_inlet_temperature,
                      pressure=0,
                      phase='l',
                      db=fluiddb)
                      
    #**************************************************************************
    
    # total flow rate
    
    mass_flow_rate = 0.075 # kg/s
    
    # number of pipes
    
    number_pipes = 15
    
    # mass flow rate per pipe
    
    mass_flow_rate_per_pipe = mass_flow_rate/number_pipes
    
    # pipe internal diameter
    
    pipe_d_int = 0.01 # m
    
    # pipe external diameter
    
    pipe_d_ext = 0.015 # not part of the exercise
    
    # pipe length
    
    pipe_length = 3
    
    # pipe thermal conductivity
    
    pipe_k = 400
    
    # create pipe object
    
    pipe = fic.Pipe(length=pipe_length,
                    k=160,
                    e_eff=0,
                    d_int=pipe_d_int,
                    d_ext=pipe_d_ext)
    
    #**************************************************************************
    
    # flow
    
    volumetric_flow_rate_per_pipe = hht_core.VolumetricFlowRateFromMassFlowRate(
        mass_flow_rate_per_pipe, fluid.mass_density)
    
    fluid_speed_per_pipe = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate_per_pipe, pipe.InternalCrossSectionalArea())
    
    reynolds_number = hht_core.ReynoldsNumber(pipe_d_int,
                                              fluid_speed_per_pipe,
                                              fluid.kinematic_viscosity)
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number, 
                                              pipe, 
                                              flow_regime)
    
    nusselt_number = fic.NusseltNumber(
        pipe, 
        friction_factor, 
        reynolds_number, 
        fluid.prandtl_number, 
        flow_regime,
        laminar_condition=fic.CONDITION_ISOTHERMAL_SURFACE)
    
    heat_transfer_coefficient = hht_core.ConvectionHeatTransferCoefficient(
        pipe.d_int,
        nusselt_number,
        fluid.thermal_conductivity)

    #**************************************************************************
    
    re_true = 1800
    
    pr_true = 2.2
    
    h_true = 308 # W/m2C
    
    nu_true = 4.6
    
    relative_tolerance = 0.075
    
    #**************************************************************************
    
    assert fluid.prandtl_number <= pr_true*(1+relative_tolerance)
    
    assert fluid.prandtl_number >= pr_true*(1-relative_tolerance)
    
    assert reynolds_number <= re_true*(1+relative_tolerance)
    
    assert reynolds_number >= re_true*(1-relative_tolerance)
    
    assert nusselt_number <= nu_true*(1+relative_tolerance)
    
    assert nusselt_number >= nu_true*(1-relative_tolerance)
    
    assert heat_transfer_coefficient <= h_true*(1+relative_tolerance)
    
    assert heat_transfer_coefficient >= h_true*(1-relative_tolerance)
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

def test_incropera2006_8dot64():
    
    # Incropera2006, page 545, Example 8.64
    
    # fluid temperature
    
    fluid_temperature = 273.15+120
    
    # mass flow rate
    
    mass_flow_rate = 500 # Kg/s
    
    # pipe diameter
    
    pipe_diameter = 1.2 # m
    
    # ground surface temperature
    
    ground_surface_temperature = 273.15-40 # celsius
    
    # soil thermal conductivity
    
    soil_k = 0.5
    
    # pipe insulation thermal conductivity
    
    ins_k = 0.05
    
    # insulation thickness
    
    ins_t = 0.15
    
    # pipe depth
    
    pipe_depth = 3
    
    # pipe length
    
    pipe_length = 100e3
    
    # fluid object
    
    fluid = fic.Fluid(phase='l',
                      temperature=fluid_temperature,
                      pressure=0,
                      mass_density=900,
                      specific_heat=2000,
                      dynamic_viscosity=2000*8.5E-4,
                      thermal_conductivity=0.14,
                      kinematic_viscosity=8.5E-4,
                      prandtl_number=1e4,
                      coefficient_expansion=0)
    
    # pipe object
    
    pipe = fic.InsulatedPipe(length=pipe_length,
                             k=1,
                             e_eff=0,
                             d_int=pipe_diameter,
                             d_ext=pipe_diameter,
                             d_ins=pipe_diameter+2*ins_t,
                             d_cas=pipe_diameter+2*ins_t,
                             k_ins=0.05,
                             k_cas=1)
    
    #**************************************************************************
    
    re_true = 694
    
    nu_true = 6.82
    
    h_true = 0.8
    
    r_line_true = 1.7 # mK/W
    
    tout_true = 110.9+273.15
    
    qloss_true = 9.1e6
    
    relative_tolerance = 0.025

    #**************************************************************************

    # flow regime

    volumetric_flow_rate = hht_core.VolumetricFlowRateFromMassFlowRate(
        mass_flow_rate, fluid.mass_density)
    
    fluid_speed = hht_core.MeanFluidSpeedViaVolumetricFlowRate(
        volumetric_flow_rate, pipe.InternalCrossSectionalArea())
    
    reynolds_number = hht_core.ReynoldsNumber(pipe.d_int,
                                              fluid_speed,
                                              fluid.kinematic_viscosity)
    
    flow_regime = fic.FlowRegime(reynolds_number)
    
    friction_factor = fic.DarcyFrictionFactor(reynolds_number,
                                              pipe,
                                              flow_regime)
    
    # heat transfer
    
    nusselt_number = fic.NusseltNumber(pipe,
                                       friction_factor,
                                       reynolds_number,
                                       fluid.prandtl_number, 
                                       flow_regime)
    
    heat_transfer_coefficient = hht_core.ConvectionHeatTransferCoefficient(
        pipe.d_int, 
        nusselt_number, 
        fluid.thermal_conductivity)
    
    
    conduction_factor = shape_factor_buried_horizontal_isothermal_cylinder(
        pipe.d_cas,
        1,
        pipe_depth)
    
    extra_specific_resistance = thermal_resistance_from_shape_factor(
        conduction_factor,
        soil_k)
    
    specific_thermal_resistance = fic.InsulatedPipeSpecificResistance(
        heat_transfer_coefficient, 
        np.inf, 
        extra_specific_resistance, 
        pipe)
    
    thermal_resistance = specific_thermal_resistance/pipe.length
    
    (pipe_efficiency, 
     outlet_temperature,
     heat_transfer_rate) = fic.PipeHeatTransferCalculations(
         pipe=pipe, 
         fluid_in=fluid, 
         fluid_bulk=fluid, 
         fluid_speed=fluid_speed, 
         heat_transfer_condition=fic.CONDITION_ISOTHERMAL_SURFACE,
         temperature_surface=ground_surface_temperature,
         thermal_resistance=thermal_resistance)
         
    #**************************************************************************
                                                
    lmtd = fic.LogMeanTemperatureDifference(fluid.temperature,
                                            outlet_temperature,
                                            ground_surface_temperature)
                                            
    surface_area = pipe.InternalSurfaceArea()
                                        
    #surface_area = 2*np.pi*pipe.length*pipe.d_int
    
    new_heat_transfer_coefficient = 1/(thermal_resistance*surface_area)
    
    # heat_transfer_rate = fic.HeatFlowRateViaLMTD(
    #     new_heat_transfer_coefficient, 
    #     lmtd, 
    #     surface_area)

    #**************************************************************************
    
    assert_allclose(reynolds_number, re_true, rtol=relative_tolerance)
    
    assert_allclose(nusselt_number, nu_true, rtol=relative_tolerance)
    
    assert_allclose(heat_transfer_coefficient, h_true, rtol=relative_tolerance)
    
    assert_allclose(specific_thermal_resistance, 
                    r_line_true, rtol=relative_tolerance)
                    
    assert_allclose(outlet_temperature, tout_true, rtol=relative_tolerance)
                
    assert_allclose(-heat_transfer_rate, qloss_true, rtol=relative_tolerance)
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************